<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>
		<script src="js/lodash-4.17.21.js"></script>
		<script type="text/javascript">
			{
				const source = {
					source: 'ab',
					get g() {
						return this.source
					},
					set s(val) {
						this.source = val
					}
				}
				const target = {}
				// source.source = 'cd'
				const assign = Object.assign(target, source)
				console.log(assign, 'assign')
			}

			{
				// 当属性值是基本数据类型时，进行的是深拷贝。
				var obj = {
					name: 'Jack'
				};
				var obj2 = Object.assign({}, obj);
				obj2.name = 'Tom';
				console.log(obj.name, obj2.name); // Jack Tom
			}

			{
				// Object.assign()拷贝的是属性值。当属性值是一个指向对象的引用，它也只能拷贝那个引用值，而不会拷贝被引用的那个对象。
				var obj = {
					base: {
						name: 'Jack'
					}
				};
				var obj2 = Object.assign({}, obj);
				obj2.base.name = 'Tom';
				console.log(obj.base.name, obj2.base.name); // Tom Tom
			}

			{
				let arr = [1, 3, {
					username: 'mary'
				}];
				let arr2 = arr.concat();
				arr2[2].username = 'maryong';
				arr2[1] = '5';
				console.log(arr, arr2); // [1, 3, { username: 'maryong' }], [1, '5', { username: 'maryong' }]
			}

			{
				let arr = [1, 3, {
					username: ' mary'
				}];
				let arr3 = arr.slice();
				arr3[2].username = 'maryong'
				arr3[1] = '5';
				console.log(arr, arr3);
			}

			{
				// 实现一个Object.create()
				Object.myCreate = function(obj, properties) {
					var F = function() {}
					F.prototype = obj
					if (properties) {
						Object.defineProperties(F, properties)
					}
					return new F()
				}
				Object.myCreate({}, {
					a: {
						value: 1
					}
				}) // {a: 1}
			}

			{
				// 复现new的构造过程
				var objectFactory = function() {
					var obj = new Object() // 从Object.prototype上克隆一个空对象 此时 __proto__ 指向Object.prototype
					var Constructor = [].shift.call(arguments) //取得构造器
					obj.__proto__ = Constructor.prototype // 指向构造器的prototype
					var ret = Constructor.apply(obj, arguments)
					return typeof ret === 'object' ? ret : obj
				}
				function Person(name) {
					this.name = name
				}
				Person.prototype.getName = function() {
					return this.name
				}
				var a = objectFactory(Person, 'mary')
				console.log(a.name) // mary
				console.log(a.getName()) // mary
				console.log(Object.getPrototypeOf(a) === Person.prototype) // true
			}

			{
				// 方法1：使用for...in循环和delete操作符来删除指定的属性。
				function filterProperties(obj, keys) {
					for (let key in obj) {
						if (keys.includes(key)) {
							delete obj[key];
						}
					}
					return obj;
				}

				// 方法2：使用解构赋值和Object.assign()方法来复制对象，然后使用delete操作符删除指定的属性。
				function filterProperties3(obj, keys) {
					let filteredObj = Object.assign({}, obj);
					for (let key of keys) {
						delete filteredObj[key];
					}
					return filteredObj;
				}

				// 方法3：使用Object.keys()方法和Array.prototype.filter()方法来筛选需要保留的属性。
				function filterProperties2(obj, keys) {
					return Object.keys(obj).filter(key => !keys.includes(key)).reduce((result, key) => {
						console.log(result, key)
						result[key] = obj[key];
						return result;
					}, {});
				}

				const obj = {
					name: 'a',
					age: 18,
					sex: 'man',
					work: 'dev',
					skill: 'study',
					hobby: 'play'
				}
				const filterProp = filterProperties3(obj, ['work', 'skill', 'hobby'])
				console.log(filterProp, 'omitProp')
			}

			{
				function keepOnly(obj, keys) {
					let keepObj = Object.create(null)
					// for (let key in obj) {
					// 	if (keys.includes(key)) {
					// 		keepObj[key] = obj[key];
					// 	}
					// }
					for (let key of keys) {
						keepObj[key] = obj[key];
					}
					return keepObj;
				}

				function keepOnly2(obj, props) {
					return Object.keys(obj)
						.filter(key => props.includes(key))
						.reduce((result, key) => {
							result[key] = obj[key];
							return result;
						}, {});
				}

				const originalObj = {
					a: 1,
					b: 2,
					c: 3,
					d: 4
				};
				const propsToKeep = ['a', 'c'];
				const newObj = keepOnly(originalObj, propsToKeep);
				console.log(newObj, 'pickProp'); // { a: 1, c: 3 }
			}
		</script>
	</body>
</html>